<template>
  <div class="video-crop-container">
    <div class="video-container" ref="videoContainerRef">
      <div class="video-real-size" ref="videoWrapper">
        <video ref="videoPlayer" :src="videoUrl" @loadedmetadata="getVideoDimensions" class="video" :controls="false"></video>
        <VueDragResize v-if="crop_box_data.width && crop_box_data.height" ref="cropBox"  :w="crop_box_data.width"
          :h="crop_box_data.height" :x="crop_box_data.x" :y="crop_box_data.y" 
          :minw="128" :minh="128" 
          parentLimitation :is-resizable="true"
          :is-draggable="true" :aspectRatio="isAspectRatio" @resizing="onResizing" @dragging="onDragging"
          class="crop-box">
        </VueDragResize>

      </div>

    </div>
   
    <div class="crop-ratio-box">
      <videoControl :videoRef="videoPlayer" :videoDuration="videoDuration" ref="videoControlRef"></videoControl>
      <div class="flex justify-between  w-full mt-10 px-25 pt-10">
        <div>
          
          <a-radio-group v-model:value="current_ratio" @change="handleRatioChange" :options="ratioList" />
        </div>
      
      <div >
       
        <a-button class="ml-5" type="primary" @click="startCrop" :loading="loading"> <a-tooltip v-if="numUnitValue&&numConsumesValue&&nameValue">
            <template #title>
              <span v-if="numUnitValue&&numConsumesValue&&nameValue">每{{numUnitValue}}消耗{{pointConsumesValue}}{{pointUnitValue}}{{ nameValue }}, 不足1{{numUnitValue}}按1{{pointUnitValue}}计算</span>
            </template>
            <question-circle-outlined  />
          </a-tooltip>开始裁剪</a-button>
        <a-button class="ml-5" @click="cancelCrop">取消裁剪</a-button>
      </div>
    </div>
   
    </div>
   
    <div class="mask" v-if="loading">
      <div class="loading">
	      <span>制作中...</span>
	    </div>
    </div>
  </div>
</template>
<script setup>
import VueDragResize from 'vue-drag-resize/src';
import { LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons-vue';
import { ref, reactive, computed, watch, onMounted, nextTick } from "vue";
import videoControl from "../components/VideoControl.vue";
import { getComputingPowerDetail,useModal,useTextToH } from "../utils/index.js";

const props = defineProps({
  videoUrl: {
    type: String,
    default: ""
  },
  loading:{
    type:Boolean,
    default:false,
  }
})
const emit = defineEmits(['cancelCrop','startCrop'])
// 获取视频的原始宽高
let videoPlayer = ref()
let videoRealWidth = ref(0)
let videoRealHeight = ref(0)
let videoCssWdith = ref(0)
let videoCssHeight = ref(0)
let videoContainerRef = ref()
let videoDuration = ref(0)
let videoControlRef = ref()
let numUnitValue = ref("");
let numConsumesValue = ref("");
let pointConsumesValue = ref("");
let nameValue = ref("");
let pointUnitValue = ref("");

// 新增响应式数据
const videoWrapper = ref(null);

let isPlaying = ref(false)
const crop_box_data = reactive({
  width: 0,
  height: 0,
  x: 0,
  y: 0
})
let current_ratio = ref(1)
/**
 * 将CSS尺寸坐标转换到原始视频尺寸坐标系
 * @param {Object} cssCrop  CSS尺寸的裁剪参数 {x, y, width, height}
 * @param {number} videoCssWidth  视频在页面中的实际渲染宽度
 * @param {number} videoCssHeight 视频在页面中的实际渲染高度
 * @param {number} videoRealWidth  视频原始宽度
 * @param {number} videoRealHeight 视频原始高度
 * @returns {Object} 原始视频坐标系中的参数
 */
 function convertCropToOriginal(cssCrop, videoCssWidth, videoCssHeight, videoRealWidth, videoRealHeight) {
  // 核心计算逻辑
  const scaleX = videoCssWidth / videoRealWidth
  const scaleY = videoCssHeight / videoRealHeight
  
  // 比例容错处理（保护非标准缩放模式）
  if (Math.abs(scaleX - scaleY) > 0.01) {
    console.warn('非等比缩放模式，转换结果可能不准确')
  }

  let scaleX_int = scaleX.toFixed(3)
  let scaleY_int = scaleY.toFixed(3)
  
  // 计算反向映射
  return {
    x: Math.floor(cssCrop.x / scaleX_int),
    y: Math.floor(cssCrop.y / scaleY_int),
    width: Math.floor(cssCrop.width / scaleX_int),
    height: Math.floor(cssCrop.height / scaleY_int)
  }
}
// 计算最大公约数（GCD）的函数
const gcd = (a, b) => b === 0 ? a : gcd(b, a % b)
// 将宽高转换为最简比例的公式
const getAspectRatio = (width, height) => {
  const divisor = gcd(width, height)
  return `${width / divisor}:${height / divisor}`
}
// 比例配置
const ASPECT_RATIO_CONFIG = {
  '1:1': {
    label: '1:1',

    calc: (videoCssWdith, videoCssHeight) => {
      const size = Math.min(videoCssWdith, videoCssHeight)
      return { width: size, height: size }
    }
  },
  '16:9': {
    label: '16:9',

    calc: (videoCssWdith, videoCssHeight) => {
      const size = Math.min(videoCssWdith, videoCssHeight)
      return { width: size * 16 / 9, height: size }
    }
  },
  '9:16': {
    label: '9:16',
    calc: (videoCssWdith, videoCssHeight) => {
      const size = Math.min(videoCssWdith, videoCssHeight)
      return { width: size, height: size / 9 * 16 }
    }
  },
  '4:3': {
    label: '4:3',
    calc: (videoCssWdith, videoCssHeight) => {
      const size = Math.min(videoCssWdith, videoCssHeight)
      return { width: size * 4 / 3, height: size }
    }
  },
  'original': {
    label: '原始比例',
    calc: (videoCssWdith, videoCssHeight) => {
      return { width: videoCssWdith, height: videoCssHeight }
    }
  },
  'free': {
    label: '自由裁剪',
    calc: (videoCssWdith, videoCssHeight) => {
      const size = Math.min(videoCssWdith, videoCssHeight)
      return { width: size, height: size }
    }
  }
}
const ratioList = ref(Object.entries(ASPECT_RATIO_CONFIG).map(([value, config]) => ({
  value,
  label: config.label,
})))
let isAspectRatio = computed(() => {
  return current_ratio.value == 'free' ? false : true
})

const startCrop = async () => {
  const data = await getComputingPowerDetail({key:'extract_video_clip_point'})
        
  let content = useTextToH({...data,title:'视频裁剪'})
  useModal({title:'视频裁剪',data,content}).then(()=>{
   
    const videoCssWdith = videoPlayer.value.offsetWidth
    const videoCssHeight = videoPlayer.value.offsetHeight
    const videoRealWidth = videoPlayer.value.videoWidth
    const videoRealHeight = videoPlayer.value.videoHeight
    let res = convertCropToOriginal(crop_box_data, videoCssWdith, videoCssHeight, videoRealWidth, videoRealHeight)
    let videoCropTimeData = videoControlRef.value.getCropTime()
    emit('startCrop',{...res, ...videoCropTimeData})
  })
  
}
const cancelCrop = () => {
  emit('cancelCrop')
}
const togglePlay = () => {
  if (videoPlayer.value.paused) {
    videoPlayer.value.play();
    isPlaying.value = true;
  } else {
    videoPlayer.value.pause();
    isPlaying.value = false;
  }
}
const ratioChange = (init = false) => {
  // return new Promise((resolve, reject) => {
  //   setTimeout(() => {
      initCropBoxData(init)
  //   }, 100)
  //   resolve()
  // })
}
function autoFitContainer(parentWidth, parentHeight, childWidth, childHeight) {
  // 边界检查
  if (parentWidth <= 0 || parentHeight <= 0) {
    throw new Error("Invalid container dimensions")
  }
  if (childWidth <= 0 || childHeight <= 0) {
    return {width:parentWidth, height:parentHeight}// 返回最大尺寸
  }
  // 计算宽高比
  const containerRatio = parentWidth / parentHeight
  const childRatio = childWidth / childHeight
  // 根据宽高比关系动态选择缩放方向
  let targetWidth, targetHeight

  if (childRatio > containerRatio) {
    // 水平方向填满，垂直居中
    targetWidth = parentWidth
    targetHeight = parentWidth / childRatio
  } else {
    // 垂直方向填满，水平居中
    targetHeight = parentHeight
    targetWidth = parentHeight * childRatio
  }
  // 返回整数尺寸
  return { width: Math.round(targetWidth), height: Math.round(targetHeight) }
}

const initCropBoxData = async (init = false) => {
  let parentWidth = videoContainerRef.value.offsetWidth
  let parentHeight = videoContainerRef.value.offsetHeight
  let videoRealWidth = videoPlayer.value.videoWidth
  let videoRealHeight = videoPlayer.value.videoHeight
  let videoAspectString = getAspectRatio(videoRealWidth, videoRealHeight)
  if (init) {
    current_ratio.value = videoAspectString
    //  如果不是标准视频比例（在ratioList中的比例）
    if (ratioList.value.findIndex(item => item.value == videoAspectString) == -1) {
      current_ratio.value = 'free'
    }
  }

  let { width: finalParentWidth, height: finalParentHeight } = autoFitContainer(parentWidth, parentHeight, videoRealWidth, videoRealHeight)
  videoCssWdith.value = finalParentWidth + 'px'
  videoCssHeight.value = finalParentHeight  + 'px'

  crop_box_data.x = 0
  crop_box_data.y = 0
  await nextTick()
  const { width, height } = ASPECT_RATIO_CONFIG[current_ratio.value].calc(videoPlayer.value.offsetWidth, videoPlayer.value.offsetHeight)
  let videoCssWdithValue = Math.floor(width)
  let videoCssHeightValue = Math.floor(height)
  let videoBoundWidth = videoPlayer.value.offsetWidth
  let videoBoundHeight = videoPlayer.value.offsetHeight

  
  let { width: finalWidth, height: finalHeight } = autoFitContainer(videoBoundWidth, videoBoundHeight, videoCssWdithValue, videoCssHeightValue)
  crop_box_data.width = finalWidth
  crop_box_data.height = finalHeight

}

const getVideoDimensions = () => {
  initCropBoxData(true)
  videoDuration.value = videoPlayer.value.duration
}
const onResizing = (options) => {
  crop_box_data.x = options.left
  crop_box_data.y = options.top
  crop_box_data.width = options.width
  crop_box_data.height = options.height
}
const onDragging = (options) => {
  crop_box_data.x = options.left
  crop_box_data.y = options.top
  crop_box_data.width = options.width
  crop_box_data.height = options.height
}
const handleRatioChange = () => {
  crop_box_data.width = 0
  crop_box_data.height = 0
  crop_box_data.x = 0
  crop_box_data.y = 0
  ratioChange(false)
}
getComputingPowerDetail({key:'extract_video_clip_point'}).then((res) => {
  console.log(res,'xxxxxxxxxxxxxx');
  
  if (res) {
    let {
      numberInfo:{unit:numUnit,consumes:numConsumes},
      pointInfo:{unit:pointUnit,consumes:pointConsumes,name}
    } = res; 
    console.log(numUnit,numConsumes,pointConsumes,name,pointUnit);
    
    numUnitValue.value = numUnit;
    numConsumesValue.value = numConsumes;
    pointConsumesValue.value = pointConsumes;
    nameValue.value = name;
    pointUnitValue.value = pointUnit;
  } 
})
</script>
<style lang="less" scoped>
.video-crop-container {
  position: relative;
}


.video-container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  width: 100%;
  height: 600px;
  background-color: rgba(0, 0, 0, 0.5);
}

.video-real-size {
  position: relative;
  width: v-bind(videoCssWdith);
  height: v-bind(videoCssHeight);
}

.video {
  position: relative;
  width: 100%;
  object-fit: contain;
}


.crop-box {
  outline: 2px dashed  #00ff00;;
  position: absolute;
  cursor: move;
}

.crop-ratio-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.mask{
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  font-size: 16px;
  color:#fff;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999;
  cursor: not-allowed;
  .loading{
				color:white;
				width: 120px;
				height: 120px;
				box-sizing: border-box;
				border-radius: 50%;
				border-top: 10px solid #e74c3c;
				position:relative;
				animation: a1 2s linear infinite;
			}
			.loading span{
				width: 120px;
				height: 120px;
				display: block;
				text-align: center;
				line-height: 120px;
				animation: a2 2s linear infinite;
			}
		   .loading:before,.loading:after{
			   content: '';
			   width: 120px;
			   height: 120px;
			   position: absolute;
			   left: 0;
			   top: -10px;
			   box-sizing: border-box;
			   border-radius: 50%;
		   }
		    .loading:before{
				border-top: 10px solid lawngreen;
				transform: rotate(120deg);
			}
			.loading:after{
				border-top: 10px solid var(--ss-primary-color);
				transform: rotate(-120deg);
			}
			
			@keyframes a1{
				to{
					transform: rotate(360deg);
				}
			}
			@keyframes a2{
				to{
					transform: rotate(-360deg);
				}
			}  
}
.coast-tip-wrap{
 width: 100%;

}
.coast-tip{
  color: #aaa;
  margin-left: 20px;
}
</style>